/**
 * @file speed.c
 * @brief 速度处理文件
 * @details 实现GPS速度数据处理、单位转换、轨迹记录等功能
 * @author 开发者
 * @date 创建日期
 */

#include "speed.h"

/* 全局变量 */
static double speed_km_H = 0;  // 当前速度（公里/小时）
/**
 * @brief 获取速度并转换为公里/小时
 * @param speed GPS原始速度数据（节）
 * @details 将GPS速度从节转换为公里/小时
 */
void get_speed(uint8_t *speed)
{
    float speed_get = 0;
    sscanf((char *)speed, "%f", &speed_get);  // 从字符串解析速度值
    // 将节转换为公里/小时（1节 = 1.852公里/小时）
    speed_km_H = speed_get * 1.852;
    printf("%.1f \n", speed_km_H);  // 打印转换后的速度
}

/**
 * @brief 获取当前速度并更新UI显示
 * @param GET_KM_H 速度输出缓冲区
 * @details 格式化速度显示，并根据速度值更新UI提示
 */
void get_speed_H(char * GET_KM_H)
{
    sprintf(GET_KM_H,"%.1f",speed_km_H);  // 格式化速度显示
    if(speed_km_H < SPEED_HIGH) {
        lv_label_set_text(ui_SPEEDUP, "SPEED UP");  // 速度较低，提示加速
    } else {
        lv_label_set_text(ui_SPEEDUP, "SLOW DOWN");  // 速度较高，提示减速
    }

#ifdef GPS_DEBUG
    printf("%s",GET_KM_H);  // 调试信息打印
#endif
}

/**
 * @brief 计算每秒前进的距离（米/秒）
 * @return double 每秒前进的距离
 * @details 将公里/小时转换为米/秒
 */
static double speed_s()
{
    // 将公里/小时转换为公里/秒
    double km_S = speed_km_H * 1000 / 3600;  // 转换为米/秒

    // 输出转换后的速度
    printf("%.2f\n",km_S);
    return km_S;
}
/* 外部队列句柄声明 */
extern QueueHandle_t  TRK_TRP_Stust;  // 轨迹航点状态队列

/**
 * @brief 轨迹和航点距离计算函数
 * @param SHOW_TRK 总骑行距离输出缓冲区
 * @param SHOW_TRP 单次骑行距离输出缓冲区
 * @details 计算总骑行距离和单次骑行距离，并保存到备份寄存器
 */
void TRK_TRP(char* SHOW_TRK,char * SHOW_TRP) {
    // 读取时间组的第一个值
    static uint8_t num = 0;      // 接收到的状态值
    static uint8_t syn = 0;      // 同步标志
    static uint8_t flag = 0;     // 骑行标志
    
    /* 从队列接收数据 */
    xQueueReceive(
        TRK_TRP_Stust,           // 队列句柄
        &num,                    // 接收数据指针
        pdTRUE                   // 永久等待
    );
    
    // 总骑行距离
    static double TRK = 0;       // 总骑行距离（公里）
    
    /* 开机时同步一次值 */
    if(syn == 0) {
        if(RTC_BKP2 != 0) {
            rcu_periph_clock_enable(RCU_PMU);   // 使能电源管理单元时钟
            pmu_backup_write_enable();          // 使能备份域写操作
            TRK = RTC_BKP2 / 10.0;             // 从备份寄存器读取总距离
            rcu_periph_clock_disable(RCU_PMU);  // 禁用电源管理单元时钟
            pmu_backup_write_disable();         // 禁用备份域写操作
            syn = 1;                            // 设置同步标志
        }
    }
    
    // 单次骑行距离
    static double TRP = 0;       // 单次骑行距离（公里）
    static int temp_mili = 0;    // 临时毫秒计数器
    
    /* 处理开始骑行信号（num == 10） */
    if (num == 10) {
        double get_s_speed;

        get_s_speed = speed_s();  // 获取当前速度（米/秒）
        temp_mili += get_s_speed; // 累加距离
        
        /* 每100米更新一次距离 */
        if(temp_mili >= 100) {
            temp_mili = 0;        // 重置临时计数器
            TRP += 0.1;           // 单次骑行距离增加0.1公里
            TRK += 0.1;           // 总骑行距离增加0.1公里
        }
        flag = 1;                 // 设置骑行标志
    }
    
    /* 处理停止骑行信号（num == 20） */
    if(num == 20) {
#ifdef GPS_DEBUG
        printf("TRP TEMPMILI RESET \n");  // 调试信息
#endif
        if(flag == 1) {
            TRP = 0;              // 重置单次骑行距离
            temp_mili = 0;        // 重置临时计数器
            flag = 0;             // 清除骑行标志
        }
    }
    
    /* 格式化距离显示 */
    sprintf(SHOW_TRP,"%.1f",TRP);  // 格式化单次骑行距离
    sprintf(SHOW_TRK,"%.1f",TRK);  // 格式化总骑行距离
    
    /* 存储值到备份域寄存器 */
    rcu_periph_clock_enable(RCU_PMU);   // 使能电源管理单元时钟
    pmu_backup_write_enable();          // 使能备份域写操作
    RTC_BKP2 = TRK * 10;               // 保存总距离到备份寄存器（乘以10避免浮点数）
    rcu_periph_clock_disable(RCU_PMU);  // 禁用电源管理单元时钟
    pmu_backup_write_disable();         // 禁用备份域写操作
}